#include <fstream>
#include <iostream>
#include <regex>
#include <string>

#include "temp_code.cxx"

void printHelp()
{
    std::cout << "Usage : genQWidget "
              << " [-t [widget dialog object]] <class_name>" << std::endl;
}

void genCode(const std::string &targetName, const std::string &widgetType);

std::string toUpper(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), ::toupper);
    return s;
}

std::string toLower(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), ::tolower);
    return s;
}

int main(int argc, char **argv)
{
    std::string targetName;
    std::string widgetType;
    auto re_type = std::regex(R"(\s*-([\S])\s*)", std::regex_constants::ECMAScript);

    for (int i = 1; i < argc; i++)
    {
        auto s = std::string(argv[i]);
        std::smatch match;
        bool hasmatch = std::regex_search(s, match, re_type) != 0;
        bool hastype = false;

        if (match.size() > 1)
        {
            auto param = match[1].str();
            if (param.find("t") == std::string::npos && param.find("h") == std::string::npos)
            {
                std::cerr << "Invalid argument : -" << argv[i] << std::endl;
                printHelp();
                return 1;
            }

            if (param.find("h") != std::string::npos)
            {
                printHelp();
                return 0;
            }
            else if (match.str().find("t") != std::string::npos)
            {
                hastype = true;
            }
        }

        if (hasmatch && hastype && i + 1 < argc)
        {
            widgetType = argv[i + 1];
            i++;
        }
        else
        {
            targetName = argv[i];
        }
    }

    if (widgetType.empty())
    {
        widgetType = "widget";
    }
    else if (widgetType != "widget" && widgetType != "dialog" && widgetType != "object")
    {
        std::cerr << "Invalid argument : -t " << widgetType << std::endl;
        printHelp();
        return 1;
    }

    if (targetName.empty())
    {
        std::cerr << "class name is empty!" << std::endl;
        printHelp();
        return 1;
    }

    genCode(targetName, widgetType);

    return 0;
}

void genCode(const std::string &targetName, const std::string &widgetType)
{
    auto classname_lower = toLower(targetName);
    auto classname_upper = toUpper(targetName);
    std::string uixml, header, cppsrc;

    if (widgetType == "dialog")
    {
        uixml = std::string(MyDialogUiXml);
        header = std::string(MyDialogHeader);
        cppsrc = std::string(MyDialogCpp);
    }
    else if (widgetType == "widget")
    {
        uixml = std::string(MyWidgetUiXml);
        header = std::string(MyWidgetHeader);
        cppsrc = std::string(MyWidgetCpp);
    }
    else
    {
        uixml = std::string(); //MyObjectUiXml
        header = std::string(MyObjectHeader);
        cppsrc = std::string(MyObjectCpp);
    }

    auto re_c = std::regex("MyWidget");
    auto re_u = std::regex("MYWIDGET");

    if (!uixml.empty())
    {
        uixml = std::regex_replace(uixml, re_c, targetName);
    }

    header = std::regex_replace(header, re_c, targetName);
    header = std::regex_replace(header, re_u, classname_upper);

    cppsrc = std::regex_replace(cppsrc, re_c, targetName);
    cppsrc = std::regex_replace(cppsrc, std::regex("ui_mywidget.h"), "ui_" + classname_lower + ".h");
    cppsrc = std::regex_replace(cppsrc, std::regex("mywidget.h"), targetName + ".h");

    if (!uixml.empty())
    {
        std::cout << "/******************** uixml ********************/\n" << uixml << std::endl;
    }
    std::cout << "/******************** header ********************/\n" << header << std::endl;
    std::cout << "/******************** cppsrc ********************/\n" << cppsrc << std::endl;
    std::cout << "/**************************************************/\n\n";

    { // 文件存在就不生成代码了
        
        std::ifstream header_file(targetName + ".h");
        std::ifstream cpp_file(targetName + ".cpp");

        if (!uixml.empty())
        {
            std::ifstream uixml_file(targetName + ".ui");
            if (uixml_file.is_open())
            {
                uixml_file.close();
                std::cerr << targetName << ".ui already exist!" << std::endl;
                return;
            }
        }
        if (header_file.is_open())
        {
            header_file.close();
            std::cerr << targetName << ".h already exist!" << std::endl;
            return;
        }
        if (cpp_file.is_open())
        {
            cpp_file.close();
            std::cerr << targetName << ".cpp already exist!" << std::endl;
            return;
        }
    }

    if (!uixml.empty())
    {
        std::ofstream uixml_file(targetName + ".ui");
        uixml_file << uixml;
    }

    std::ofstream header_file(targetName + ".h");
    std::ofstream cpp_file(targetName + ".cpp");

    header_file << header;
    cpp_file << cppsrc;
}
